# -*- coding: utf-8 -*-
"""
规则模板管理服务模块
实现动态模板配置和管理功能

主要功能:
- 模板CRUD操作
- 模板渲染和变量替换
- 模板分类管理
- 模板版本控制
"""

import re
import json
from typing import Dict, Any, List, Optional, Tuple
from datetime import datetime, timezone
import logging
from jinja2 import Template, Environment, BaseLoader, TemplateError
from dataclasses import dataclass, asdict
from enum import Enum

# 暂时使用内存存储，简化架构
_template_storage = {}
_template_counter = 0

# 配置日志
logger = logging.getLogger(__name__)


class TemplateType(Enum):
    """模板类型枚举"""
    MARKETING_PLAN = "marketing_plan"  # 营销方案
    CONTENT_STRATEGY = "content_strategy"  # 内容策略
    CAMPAIGN_IDEA = "campaign_idea"  # 活动创意
    AD_COPY = "ad_copy"  # 广告文案
    SOCIAL_MEDIA = "social_media"  # 社交媒体
    EMAIL_MARKETING = "email_marketing"  # 邮件营销
    SYSTEM_PROMPT = "system_prompt"  # 系统提示词
    USER_PROMPT = "user_prompt"  # 用户提示词


@dataclass
class TemplateVariable:
    """模板变量数据类"""
    name: str
    type: str  # string, number, boolean, array, object
    description: str
    required: bool = True
    default_value: Any = None
    validation_rules: Optional[Dict[str, Any]] = None
    
    def validate_value(self, value: Any) -> Tuple[bool, Optional[str]]:
        """
        验证变量值
        
        Args:
            value: 要验证的值
            
        Returns:
            Tuple[bool, Optional[str]]: (是否有效, 错误信息)
        """
        # 检查必填项
        if self.required and (value is None or value == ''):
            return False, f"变量 '{self.name}' 是必填项"
        
        # 如果值为空且不是必填项，使用默认值
        if value is None or value == '':
            if self.default_value is not None:
                value = self.default_value
            else:
                return True, None
        
        # 类型检查
        if self.type == 'string' and not isinstance(value, str):
            return False, f"变量 '{self.name}' 必须是字符串类型"
        elif self.type == 'number' and not isinstance(value, (int, float)):
            return False, f"变量 '{self.name}' 必须是数字类型"
        elif self.type == 'boolean' and not isinstance(value, bool):
            return False, f"变量 '{self.name}' 必须是布尔类型"
        elif self.type == 'array' and not isinstance(value, list):
            return False, f"变量 '{self.name}' 必须是数组类型"
        elif self.type == 'object' and not isinstance(value, dict):
            return False, f"变量 '{self.name}' 必须是对象类型"
        
        # 验证规则检查
        if self.validation_rules:
            if self.type == 'string':
                min_length = self.validation_rules.get('min_length')
                max_length = self.validation_rules.get('max_length')
                pattern = self.validation_rules.get('pattern')
                
                if min_length and len(value) < min_length:
                    return False, f"变量 '{self.name}' 长度不能少于 {min_length} 个字符"
                if max_length and len(value) > max_length:
                    return False, f"变量 '{self.name}' 长度不能超过 {max_length} 个字符"
                if pattern and not re.match(pattern, value):
                    return False, f"变量 '{self.name}' 格式不正确"
            
            elif self.type == 'number':
                min_value = self.validation_rules.get('min_value')
                max_value = self.validation_rules.get('max_value')
                
                if min_value is not None and value < min_value:
                    return False, f"变量 '{self.name}' 不能小于 {min_value}"
                if max_value is not None and value > max_value:
                    return False, f"变量 '{self.name}' 不能大于 {max_value}"
            
            elif self.type == 'array':
                min_items = self.validation_rules.get('min_items')
                max_items = self.validation_rules.get('max_items')
                
                if min_items and len(value) < min_items:
                    return False, f"变量 '{self.name}' 至少需要 {min_items} 个元素"
                if max_items and len(value) > max_items:
                    return False, f"变量 '{self.name}' 最多只能有 {max_items} 个元素"
        
        return True, None


class TemplateService:
    """模板管理服务类"""
    
    def __init__(self):
        self.jinja_env = Environment(loader=BaseLoader())
        # 初始化一些默认模板
        self._init_default_templates()
    
    def _init_default_templates(self):
        """初始化默认模板"""
        global _template_storage, _template_counter
        
        # 营销方案模板
        default_template = {
            'id': 'template_1',
            'name': '营销方案模板',
            'description': '通用营销方案生成模板',
            'template_type': 'marketing_plan',
            'category': '营销方案',
            'content': '''# {{product_name}}营销方案\n\n## 产品概述\n产品名称：{{product_name}}\n目标用户：{{target_audience}}\n预算范围：{{budget}}\n\n## 营销策略\n{{marketing_strategy}}\n\n## 执行计划\n{{execution_plan}}''',
            'variables': [
                {'name': 'product_name', 'type': 'string', 'description': '产品名称', 'required': True},
                {'name': 'target_audience', 'type': 'string', 'description': '目标用户群体', 'required': True},
                {'name': 'budget', 'type': 'string', 'description': '预算范围', 'required': True},
                {'name': 'marketing_strategy', 'type': 'string', 'description': '营销策略', 'required': True},
                {'name': 'execution_plan', 'type': 'string', 'description': '执行计划', 'required': True}
            ],
            'tags': ['营销', '方案', '通用'],
            'is_system': True,
            'is_active': True,
            'version': 1,
            'created_at': datetime.now(timezone.utc),
            'updated_at': datetime.now(timezone.utc)
        }
        
        _template_storage['template_1'] = default_template
        _template_counter = 1
    
    async def create_template(
        self,
        name: str,
        description: str,
        template_type: str,
        category: str,
        content: str,
        variables: List[Dict[str, Any]],
        tags: Optional[List[str]] = None,
        is_system: bool = False,
        created_by: Optional[str] = None
    ) -> Optional[str]:
        """
        创建模板
        
        Args:
            name: 模板名称
            description: 模板描述
            template_type: 模板类型
            category: 模板分类
            content: 模板内容
            variables: 模板变量列表
            tags: 标签列表
            is_system: 是否系统模板
            created_by: 创建者ID
            
        Returns:
            Optional[str]: 模板ID
        """
        try:
            # 验证模板内容
            validation_result = self._validate_template_content(content, variables)
            if not validation_result[0]:
                logger.error(f"模板内容验证失败: {validation_result[1]}")
                return None
            
            # 创建模板数据
            template_data = {
                'name': name,
                'description': description,
                'template_type': template_type,
                'category': category,
                'content': content,
                'variables': variables,
                'tags': tags or [],
                'is_system': is_system,
                'is_active': True,
                'version': 1,
                'created_by': created_by
            }
            
            # 生成模板ID
            global _template_counter
            _template_counter += 1
            template_id = f'template_{_template_counter}'
            
            # 添加时间戳和ID
            template_data['id'] = template_id
            template_data['created_at'] = datetime.now(timezone.utc)
            template_data['updated_at'] = datetime.now(timezone.utc)
            
            # 存储到内存
            _template_storage[template_id] = template_data
            
            logger.info(f"成功创建模板: {name} (ID: {template_id})")
            return template_id
            
        except Exception as e:
            logger.error(f"创建模板失败: {e}")
            return None
    
    async def get_template(self, template_id: str) -> Optional[Dict[str, Any]]:
        """
        获取模板
        
        Args:
            template_id: 模板ID
            
        Returns:
            Optional[Dict]: 模板数据
        """
        try:
            # 从内存存储获取
            template = _template_storage.get(template_id)
            return template
            
        except Exception as e:
            logger.error(f"获取模板失败 {template_id}: {e}")
            return None
    
    async def update_template(
        self,
        template_id: str,
        update_data: Dict[str, Any],
        updated_by: Optional[str] = None
    ) -> bool:
        """
        更新模板
        
        Args:
            template_id: 模板ID
            update_data: 更新数据
            updated_by: 更新者ID
            
        Returns:
            bool: 更新是否成功
        """
        try:
            # 如果更新了内容或变量，需要验证
            if 'content' in update_data or 'variables' in update_data:
                template = await self.get_template(template_id)
                if not template:
                    return False
                
                content = update_data.get('content', template['content'])
                variables = update_data.get('variables', template['variables'])
                
                validation_result = self._validate_template_content(content, variables)
                if not validation_result[0]:
                    logger.error(f"模板内容验证失败: {validation_result[1]}")
                    return False
            
            # 检查模板是否存在
            if template_id not in _template_storage:
                return False
            
            # 添加更新信息
            if updated_by:
                update_data['updated_by'] = updated_by
            update_data['updated_at'] = datetime.now(timezone.utc)
            
            # 更新模板数据
            _template_storage[template_id].update(update_data)
            
            logger.info(f"成功更新模板: {template_id}")
            return True
            
        except Exception as e:
            logger.error(f"更新模板失败 {template_id}: {e}")
            return False
    
    async def delete_template(self, template_id: str, deleted_by: Optional[str] = None) -> bool:
        """
        删除模板
        
        Args:
            template_id: 模板ID
            deleted_by: 删除者ID
            
        Returns:
            bool: 删除是否成功
        """
        try:
            # 检查模板是否存在
            if template_id not in _template_storage:
                return False
            
            # 删除模板
            del _template_storage[template_id]
            
            logger.info(f"成功删除模板: {template_id}")
            return True
            
        except Exception as e:
            logger.error(f"删除模板失败 {template_id}: {e}")
            return False
    
    async def get_templates_by_category(
        self,
        category: str,
        template_type: Optional[str] = None,
        is_active: bool = True,
        limit: int = 50,
        offset: int = 0
    ) -> List[Dict[str, Any]]:
        """
        按分类获取模板列表
        
        Args:
            category: 模板分类
            template_type: 模板类型
            is_active: 是否激活
            limit: 限制数量
            offset: 偏移量
            
        Returns:
            List[Dict]: 模板列表
        """
        try:
            # 从内存存储筛选模板
            templates = []
            for template in _template_storage.values():
                if template.get('category') == category:
                    if template_type and template.get('template_type') != template_type:
                        continue
                    if template.get('is_active') != is_active:
                        continue
                    templates.append(template)
            
            # 分页
            return templates[offset:offset + limit]
            
        except Exception as e:
            logger.error(f"获取分类模板失败 {category}: {e}")
            return []
    
    async def search_templates(
        self,
        keyword: Optional[str] = None,
        template_type: Optional[str] = None,
        category: Optional[str] = None,
        tags: Optional[List[str]] = None,
        is_active: bool = True,
        limit: int = 50,
        offset: int = 0
    ) -> List[Dict[str, Any]]:
        """
        搜索模板
        
        Args:
            keyword: 关键词
            template_type: 模板类型
            category: 模板分类
            tags: 标签列表
            is_active: 是否激活
            limit: 限制数量
            offset: 偏移量
            
        Returns:
            List[Dict]: 模板列表
        """
        try:
            # 从内存存储搜索模板
            templates = []
            for template in _template_storage.values():
                # 检查激活状态
                if template.get('is_active') != is_active:
                    continue
                
                # 检查模板类型
                if template_type and template.get('template_type') != template_type:
                    continue
                
                # 检查分类
                if category and template.get('category') != category:
                    continue
                
                # 检查标签
                if tags:
                    template_tags = template.get('tags', [])
                    if not any(tag in template_tags for tag in tags):
                        continue
                
                # 检查关键词
                if keyword:
                    search_text = f"{template.get('name', '')} {template.get('description', '')} {template.get('content', '')}".lower()
                    if keyword.lower() not in search_text:
                        continue
                
                templates.append(template)
            
            # 分页
            return templates[offset:offset + limit]
            
        except Exception as e:
            logger.error(f"搜索模板失败: {e}")
            return []
    
    async def render_template(
        self,
        template_id: str,
        variables: Dict[str, Any]
    ) -> Tuple[bool, Optional[str], Optional[str]]:
        """
        渲染模板
        
        Args:
            template_id: 模板ID
            variables: 变量值
            
        Returns:
            Tuple[bool, Optional[str], Optional[str]]: (是否成功, 渲染结果, 错误信息)
        """
        try:
            # 获取模板
            template = await self.get_template(template_id)
            if not template:
                return False, None, "模板不存在"
            
            # 验证变量
            validation_result = self._validate_template_variables(
                template['variables'], variables
            )
            if not validation_result[0]:
                return False, None, validation_result[1]
            
            # 渲染模板
            try:
                jinja_template = self.jinja_env.from_string(template['content'])
                rendered_content = jinja_template.render(**variables)
                
                logger.debug(f"成功渲染模板: {template_id}")
                return True, rendered_content, None
                
            except TemplateError as e:
                error_msg = f"模板渲染失败: {e}"
                logger.error(error_msg)
                return False, None, error_msg
            
        except Exception as e:
            error_msg = f"渲染模板时发生错误: {e}"
            logger.error(error_msg)
            return False, None, error_msg
    
    async def get_template_categories(self) -> List[Dict[str, Any]]:
        """
        获取模板分类列表
        
        Returns:
            List[Dict]: 分类列表，包含分类名称和模板数量
        """
        try:
            # 从内存存储获取分类统计
            categories = {}
            for template in _template_storage.values():
                if template.get('is_active', True):
                    category = template.get('category', '未分类')
                    categories[category] = categories.get(category, 0) + 1
            
            return [{'name': name, 'count': count} for name, count in categories.items()]
            
        except Exception as e:
            logger.error(f"获取模板分类失败: {e}")
            return []
    
    async def get_popular_templates(self, limit: int = 10) -> List[Dict[str, Any]]:
        """
        获取热门模板
        
        Args:
            limit: 限制数量
            
        Returns:
            List[Dict]: 热门模板列表
        """
        try:
            # 从内存存储获取热门模板（按创建时间排序）
            templates = [t for t in _template_storage.values() if t.get('is_active', True)]
            templates.sort(key=lambda x: x.get('created_at', datetime.min), reverse=True)
            return templates[:limit]
            
        except Exception as e:
            logger.error(f"获取热门模板失败: {e}")
            return []
    
    def get_all_templates(self) -> List[Dict[str, Any]]:
        """
        获取所有模板列表（同步方法，用于路由调用）
        
        Returns:
            List[Dict]: 模板列表
        """
        try:
            # 从内存存储获取所有激活的模板
            templates = [t for t in _template_storage.values() if t.get('is_active', True)]
            # 按创建时间排序
            templates.sort(key=lambda x: x.get('created_at', datetime.min), reverse=True)
            return templates
            
        except Exception as e:
            logger.error(f"获取所有模板失败: {e}")
            return []
    
    def get_template_by_id(self, template_id: str) -> Optional[Dict[str, Any]]:
        """
        根据ID获取模板（同步方法，用于路由调用）
        
        Args:
            template_id: 模板ID
            
        Returns:
            Optional[Dict]: 模板数据
        """
        try:
            # 从内存存储获取
            template = _template_storage.get(template_id)
            return template
            
        except Exception as e:
            logger.error(f"获取模板失败 {template_id}: {e}")
            return None
    
    def _validate_template_content(
        self,
        content: str,
        variables: List[Dict[str, Any]]
    ) -> Tuple[bool, Optional[str]]:
        """
        验证模板内容
        
        Args:
            content: 模板内容
            variables: 变量定义列表
            
        Returns:
            Tuple[bool, Optional[str]]: (是否有效, 错误信息)
        """
        try:
            # 检查Jinja2语法
            self.jinja_env.from_string(content)
            
            # 提取模板中使用的变量
            template_vars = set(re.findall(r'{{\s*(\w+)(?:\.|\[|\s)', content))
            template_vars.update(re.findall(r'{%\s*(?:if|for)\s+(\w+)', content))
            
            # 检查变量定义
            defined_vars = {var['name'] for var in variables}
            
            # 检查未定义的变量
            undefined_vars = template_vars - defined_vars
            if undefined_vars:
                return False, f"模板中使用了未定义的变量: {', '.join(undefined_vars)}"
            
            return True, None
            
        except TemplateError as e:
            return False, f"模板语法错误: {e}"
        except Exception as e:
            return False, f"模板验证失败: {e}"
    
    def _validate_template_variables(
        self,
        variable_definitions: List[Dict[str, Any]],
        variable_values: Dict[str, Any]
    ) -> Tuple[bool, Optional[str]]:
        """
        验证模板变量
        
        Args:
            variable_definitions: 变量定义列表
            variable_values: 变量值字典
            
        Returns:
            Tuple[bool, Optional[str]]: (是否有效, 错误信息)
        """
        try:
            for var_def in variable_definitions:
                var = TemplateVariable(**var_def)
                value = variable_values.get(var.name)
                
                is_valid, error_msg = var.validate_value(value)
                if not is_valid:
                    return False, error_msg
            
            return True, None
            
        except Exception as e:
            return False, f"变量验证失败: {e}"
    
    def _clear_category_cache(self, category: str):
        """清除分类相关缓存（内存存储版本暂不需要）"""
        pass


# 全局服务实例
template_service = TemplateService()


async def get_template_service() -> TemplateService:
    """
    获取模板服务实例
    
    Returns:
        TemplateService: 服务实例
    """
    return template_service


# 便捷函数
async def create_marketing_template(
    name: str,
    description: str,
    content: str,
    variables: List[Dict[str, Any]],
    category: str = "营销方案",
    tags: Optional[List[str]] = None,
    created_by: Optional[str] = None
) -> Optional[str]:
    """
    创建营销模板的便捷函数
    
    Args:
        name: 模板名称
        description: 模板描述
        content: 模板内容
        variables: 变量列表
        category: 分类
        tags: 标签
        created_by: 创建者
        
    Returns:
        Optional[str]: 模板ID
    """
    return await template_service.create_template(
        name=name,
        description=description,
        template_type=TemplateType.MARKETING_PLAN.value,
        category=category,
        content=content,
        variables=variables,
        tags=tags,
        created_by=created_by
    )


async def render_marketing_template(
    template_id: str,
    variables: Dict[str, Any]
) -> Tuple[bool, Optional[str], Optional[str]]:
    """
    渲染营销模板的便捷函数
    
    Args:
        template_id: 模板ID
        variables: 变量值
        
    Returns:
        Tuple[bool, Optional[str], Optional[str]]: (是否成功, 渲染结果, 错误信息)
    """
    return await template_service.render_template(template_id, variables)